【X68000(Z)アセンブラ講座 第034回 スプライトダブラー(試作品版)】   こんにちは!! 今回は7ヶ月ぶりの講座になり、遅くなってすみません(^^; 今回の講座までの間WinPC向けの横スク2D-STGゲームの製作や GPUのシェーダー言語の高速化の研究などをしていました。 更には先月の始めにX68000Zのキーボードが故障して マトモにテキスト入力ができなくなり絶望感に包まれたのですが とある日不意にAmazonが気になってキーボードを検索したら 運良く定価30000円位の純正品が21000円位の特価で安売りしていたので 即キーボードを注文したら4月12日に到着予定だったんだけど 瑞起さんが頑張ってくれたお陰か5日も早い7日に到着して助かりました(^^) これは天から僕に「X68000の楽しさを忘れるな」と言う運命を授けてくれたのだと思っています☆ どうやら僕も周りからX680x0(Z)のパワーユーザーとして認められているようなので 今後もX68000ZやWinPC用X68Kエミュを使って X68000(Z)のパワーユーザーとして頑張っていこうと思っています!! 皆さん、どうぞこれからも宜しくお願い致しますm(__)m 今回は僕も手こずったスプライトダブラーです。 一回の講座で完成品版の解説をしても トリッキーなプログラムの仕組みを理解し辛くて挫折する方も多いと予想されるので 理解するのが簡単で基本的な仕組みのサンプルプログラムで学習する「試作品版」と 「試作品版」をマスターした後に学習すればトリッキーな仕組みも理解しやすい「完成品版」で 2部構成に分けて学習し習得してもらう予定です。 スプライトダブラーを製作するにあたって アナログモニターかアナログテレビの画面表示の仕組みの知識が必要になります。 前もって学習しておかないとスプライトダブラーの学習は無理なので アナログ画面の仕組みの解説をしているサイトを検索するなどして学習しておいて下さい。 今回はサンプルプログラムの説明を次回の講座で行う事にして まずはプログラムの実行結果を画面で確認してみましょう。 実行すると画面がスプライト256枚で埋め尽くされます。 以下の破線の内側を'SPDBL_01.s'と言うファイル名で保存して下さい。 ------------------------------------------------------------------------------------------------ ******************************************************************************** * * アプリ名 : SPDBL_01.x * * スプライトダブラー(試作品版) * * Ver1.00 * ******************************************************************************** include A:\XC\INCLUDE\DOSCALL.MAC * OSコール用マクロの読み込み include A:\XC\INCLUDE\IOCSCALL.MAC * IOCS(BIOS)コール用マクロの読み込み * システム領域のアドレス cg_palette equ $E82000 * CG用パレットデータの先頭アドレス cg_buffer equ $C00000 * CG-VRAMの先頭アドレス cg_scroll_x equ $E80018 * CGスクロール X cg_scroll_y equ $E8001a * CGスクロール Y sp_palette equ $E82200 * スプライト用パレットデータの先頭アドレス sp_pattern equ $EB8000 * スプライトパターンデータの先頭アドレス sp_controll equ $EB0000 * スプライトスクロールレジスターの先頭アドレス vsync equ $E88001 * %00010000でV-Syncチェックする vec_vdisp equ $000118 * 垂直同期(V-DISP)割り込み vec_hsync equ $00013C * 水平同期(H-SYNC)割り込み pad1 equ $E9A001 * ゲームパッド1 pad2 equ $E9A003 * ゲームパッド2 * ラベルの定数定義 spx equ 0 spy equ 2 addx equ 4 addy equ 6 .cpu 68000 * CPUのタイプ .data * '.data'以降のデータはデータセクションに配置される .even vec118: dc.l 0 * V-Sync vec13C: dc.l 0 * H-Sync ras_num: dc.w 0 * Raster Number (現在処理中のラスター番号) sp00: dc.b $ff,$ff,$ff,$ff dc.b $f1,$11,$11,$11 dc.b $f1,$11,$11,$11 dc.b $f1,$11,$11,$11 dc.b $f1,$11,$11,$11 dc.b $f1,$11,$11,$11 dc.b $f1,$11,$11,$11 dc.b $f1,$11,$11,$11 dc.b $f1,$11,$11,$11 dc.b $f1,$11,$11,$11 dc.b $f1,$11,$11,$11 dc.b $f1,$11,$11,$11 dc.b $f1,$11,$11,$11 dc.b $f1,$11,$11,$11 dc.b $f1,$11,$11,$11 dc.b $ff,$ff,$ff,$ff dc.b $ff,$ff,$ff,$ff dc.b $11,$11,$11,$1f dc.b $11,$11,$11,$1f dc.b $11,$11,$11,$1f dc.b $11,$11,$11,$1f dc.b $11,$11,$11,$1f dc.b $11,$11,$11,$1f dc.b $11,$11,$11,$1f dc.b $11,$11,$11,$1f dc.b $11,$11,$11,$1f dc.b $11,$11,$11,$1f dc.b $11,$11,$11,$1f dc.b $11,$11,$11,$1f dc.b $11,$11,$11,$1f dc.b $11,$11,$11,$1f dc.b $ff,$ff,$ff,$ff sppal01: * GGGGG RRRRR BBBBB A dc.w %00000_00000_00000_0 dc.w %00000_00000_11111_0 dc.w %00000_00000_00000_0 dc.w %00000_00000_00000_0 dc.w %00000_00000_00000_0 dc.w %00000_00000_00000_0 dc.w %00000_00000_00000_0 dc.w %00000_00000_00000_0 dc.w %00000_00000_00000_0 dc.w %00000_00000_00000_0 dc.w %00000_00000_00000_0 dc.w %00000_00000_00000_0 dc.w %00000_00000_00000_0 dc.w %00000_00000_00000_0 dc.w %00000_00000_00000_0 dc.w %11111_11111_11111_0 .bss * '.bss'以降データバッファ .even spbuf: ds.b 2048 * [spx,spy,spdata,priority]x256 (スプライトデータバッファ) spcnt: ds.w 1 * Sprite Counter (表示するスプライトの枚数) .text * '.text'以降のプログラムはテキストセクションに配置される start: * スタートアドレス * マウスカーソルをオフにする moveq.l #_OS_CUROF,d0 trap #15 * ランダム関数の初期化 move.l #23456,d0 * d0.lにランダムのシードを代入する dc.w $FE0D * ランダムのシードを設定する * ユーザーモードからスーパーバイザーモードに移行する moveq.l #_B_SUPER,d0 * d0にIOCS(BIOS)機能番号を代入 move.l #0,d1 * 数値0をd1に代入 movea.l d1,a1 * d1をa1にコピー trap #15 * IOCSコール実行 * 画面モードの設定 moveq.l #_CRTMOD,d0 * 画面モードの設定 move.w #10,d1 * 画面モードの番号 : 16 = 768x512x4bit / 10 = 256x256x8bit trap #15 * 画面をクリアして表示をオンにする moveq.l #_G_CLR_ON,d0 * 画面をクリアして表示をオンにする trap #15 * スプライト表示をオンにする moveq.l #_SP_ON,d0 trap #15 bsr set_palette * スプライトパレット設定ルーチンの呼び出し bsr def_sprite * スプライトパターンデータの定義ルーチンの呼び出し bsr init_sprite * キャラの初期化の呼び出し * V-DISP割り込みの設定 move.l vec_vdisp,vec118 * 現在の割り込みのアドレスをバックアップ lea int_vdisp,a0 * 割り込みとしてint_vdispルーチンのアドレスを move.l a0,vec_vdisp * 割り込みベクトルに登録する。 or.b #%01000000,$E88009 * V-DISP割り込みの許可の設定 or.b #%01000000,$E88015 * V-DISP割り込みのマスクの設定 and.b #%11101111,$E88003 * 垂直帰線期間で割り込み発生 * H-SYNC割り込みの設定 move.l vec_hsync,vec13C * 現在の割り込みのアドレスをバックアップ lea int_hsync,a0 * 割り込みとしてint_hsyncルーチンのアドレスを move.l a0,vec_hsync * 割り込みベクトルに登録する。 or.b #%10000000,$E88007 * H-SYNC割り込みの許可の設定 or.b #%10000000,$E88013 * H-SYNC割り込みのマスクの設定 and.b #%01111111,$E88003 * H-SYNC信号が'L'の時に割り込み発生 loop: * メインループ開始 * V-Syncビットを監視してメインループを60fpsで動作させるタイミングを取る movea.l #vsync,a0 vsync_1: move.b (a0),d0 and.b #$10,d0 tst.b d0 beq vsync_1 vsync_2: move.b (a0),d0 and.b #$10,d0 tst.b d0 bne vsync_2 * [ESC]キーが押されたら終了処理'end:'にジャンプする moveq.l #_BITSNS,d0 moveq.l #0,d1 trap #15 and.b #%00000010,d0 tst.b d0 bne end bra loop * メインループの最初にジャンプする end: * V-DISP割り込みの終了処理 and.b #%10111111,$E88015 and.b #%10111111,$E88009 move.l vec118,vec_vdisp * H-SYNC割り込みの終了処理 and.b #%01111111,$E88007 or.b #%01111111,$E88013 move.l vec13C,vec_hsync moveq.l #_CRTMOD,d0 move.w #16,d1 trap #15 * マウスカーソルをオンにする moveq.l #_OS_CURON,d0 trap #15 * スーパーバイザーモードからユーザーモードに戻る moveq.l #_B_SUPER,d0 move.l SP,a1 trap #15 move.w #255,-(sp) dc.w _KFLUSH addq.l #2,sp * アプリ終了 dc.w _EXIT * OSコール実行 : _EXIT = プログラムの終了 int_vdisp: * V-DISP割り込みルーチン move.w #0,ras_num * 処理中ラスター番号の初期化 rte int_hsync: * H-SYNC割り込みルーチン movem.l d0/a0-a1,-(sp) * 現在の処理ラスター番号が48番の時に * 画面上半分にスプライトを128枚表示する cmp.w #48,ras_num bne int_hsync_2 lea spbuf,a0 moveq.l #128-1,d0 movea.l #sp_controll,a1 int_hsync_1: move.l (a0)+,(a1)+ move.l (a0)+,(a1)+ dblt d0,int_hsync_1 int_hsync_2: * 現在の処理ラスター番号が267番の時に * 画面下半分にスプライトを128枚表示する cmp.w #267,ras_num bne int_hsync_4 lea spbuf+1024,a0 moveq.l #128-1,d0 movea.l #sp_controll,a1 int_hsync_3: move.l (a0)+,(a1)+ move.l (a0)+,(a1)+ dblt d0,int_hsync_3 int_hsync_4: addq.w #1,ras_num * 処理するラスター番号の更新 movem.l (sp)+,d0/a0-a1 rte * RGBQUAD { Blue8, Green8, Red8, Reserved8 } = %RRRRRRRR_GGGGGGGG_BBBBBBBB_AAAAAAAA * palette { Green5, Red5, Blue5, Alpha1 } = %GGGGG_RRRRR_BBBBB_A * Set CG Palette set_palette: movea.l #sp_palette,a0 * スプライト用パレットレジスターアドレス adda.l #32,a0 lea sppal01,a1 * パレットデータバッファアドレス moveq.l #0,d7 set_palette_1: move.w (a1)+,(a0)+ addq.w #1,d7 * 色番号を次の番号に更新する cmp.w #16,d7 * 現在の色番号と16を比較する blt set_palette_1 * 現在の色番号が16未満ならアドレスset_palette_1に飛ぶ rts * 呼出元に戻る * スプライトパターンの定義 def_sprite: lea sp00,a0 movea.l #sp_pattern,a1 adda.l #128,a1 moveq.l #0,d7 def_sprite_1: move.l (a0)+,(a1)+ addq.w #1,d7 cmp.w #32,d7 blt def_sprite_1 rts * 画面全体にスプライト256枚を表示するためのスプライト座標の初期化 init_sprite: lea spbuf,a0 moveq.l #16,d2 init_sprite_1: moveq.l #16,d1 init_sprite_2: move.w d1,(a0)+ move.w d2,(a0)+ move.w #$0101,(a0)+ move.w #1,(a0)+ add.w #16,d1 cmp.w #256+16,d1 blt init_sprite_2 add.w #16,d2 cmp.w #256+16,d2 blt init_sprite_1 rts * End Of File ------------------------------------------------------------------------------------------------ ファイルの保存が終わったらコマンドプロンプトから、 A>AS SPDBL_01.s [Enter] A>LK SPDBL_01.o [Enter} A>SPDBL_01.x [Enter] 以上(↑)のように入力するとプログラムが起動します。 今回は以上です(^^) お疲れ様でした!! [EOF]